Skip to content

0.2.0: one way to author — Workflow.toLayer hosted by workflowBundle - #2

Merged
bweis merged 1 commit into
mainfrom
spike/plain-workflow-syntax
Aug 26, 2026
Merged

0.2.0: one way to author — Workflow.toLayer hosted by workflowBundle#2
bweis merged 1 commit into
mainfrom
spike/plain-workflow-syntax

Conversation

@bweis

@bweis bweis commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Prompted by Mattia Manzati's Discord suggestion that a real WorkflowEngine service could retire makeTemporalWorkflow in favor of plain @effect/workflow syntax. It does — fully. This PR makes Workflow.toLayer the only authoring form, hosted by workflowBundle.

What

  • workflowBundle(layer) — hosts Workflow.toLayer registrations behind ONE dynamic Temporal default export ("workflow bundle" is Temporal's own name for this artifact — the thing workflowsPath points at). A registration-phase engine collects engine.register calls into a per-V8-context registry (memoized, reuseV8Context-safe, duplicate tags rejected loudly); the default export dispatches by workflow type into the shared per-run wrapper.
  • BREAKING: makeTemporalWorkflow is removed. One way to author; the project is young enough to afford the break. If per-type workflowDefinitionOptions (e.g. Worker Versioning behavior) ever becomes a need, the worker-level defaultVersioningBehavior covers the dynamic workflow, and a per-type escape hatch can be reintroduced.
  • Layer-provided handler services — registered handlers can require services provided by ordinary Layers composed into the registration environment.
// workflows.ts — the whole bundle entry
export default workflowBundle(
  Layer.mergeAll(OrderFlow.toLayer(orderHandler), BillingFlow.toLayer(billingHandler)),
);

Strictly-better check

  • Type safety: the erased handler seam uses a contravariant never payload and the provided-services union for R — no any, exactly one SAFETY-commented cast, replacing the one the old code had at the same spot.
  • Coverage: every test fixture bundle (16) and both runnable examples use the bundle form, so the entire feature surface — activities, compensation, mailboxes, updates, state cells, children + attach polling, continue-as-new (re-dispatch through the default export proven end to end), versioning chains, nexus, schedules — exercises the registry path. 57/57 tests green; both examples run in CI.
  • Comment diet: constraint comments only; narration and restated-type comments trimmed.
  • Docs: the single authoring form taught throughout, no migration-era framing ("plain/upstream syntax" qualifiers removed everywhere). CHANGELOG carries the breaking 0.2.0 entry.

Release after merge: git tag v0.2.0 && git push --tags (trusted publishing).

🤖 Generated with Claude Code

@bweis
bweis force-pushed the spike/plain-workflow-syntax branch from cdf9d12 to 65198cf Compare August 26, 2026 18:52
@bweis bweis changed the title 0.2.0: plain Workflow.toLayer authoring via a dynamic default export 0.2.0: plain Workflow.toLayer authoring — one way to author workflows Aug 26, 2026
@bweis
bweis force-pushed the spike/plain-workflow-syntax branch from 65198cf to 4d8157b Compare August 26, 2026 18:58
Prompted by Mattia Manzati's suggestion that a real WorkflowEngine service
could retire makeTemporalWorkflow. It does, fully: workflowBundle(layer)
hosts `Workflow.toLayer` registrations behind ONE dynamic Temporal default
export — a registration-phase engine collects engine.register calls into a
per-context registry (memoized, reuseV8Context-safe, duplicate tags
rejected loudly) and dispatches workflow types through the per-run wrapper,
now runInSandbox. "workflowBundle" is Temporal's own name for this exact
artifact: the thing workflowsPath points at.

BREAKING: makeTemporalWorkflow is removed. One way to author; the project
is young enough to afford the break. (If per-type workflowDefinitionOptions
— e.g. Worker Versioning behavior — becomes a need, the worker-level
defaultVersioningBehavior covers the dynamic workflow, and a per-type
escape hatch can return.)

The erased handler seam is typed honestly (contravariant `never` payload,
the provided-services union for R): no `any`, exactly one SAFETY-commented
cast, replacing the one the old code had.

Registered handlers can require services provided by ordinary Layers in
the registration environment — proven in registry.test.ts. Every test
fixture bundle (16) and both examples use the bundle form, so the entire
feature surface — activities, compensation, mailboxes, updates, state
cells, children and attach, continue-as-new, versioning chains, nexus,
schedules — runs through the registry path: 57 tests green.

Docs teach the single authoring form throughout; CHANGELOG carries the
breaking 0.2.0 entry.
@bweis bweis changed the title 0.2.0: plain Workflow.toLayer authoring — one way to author workflows 0.2.0: one way to author — Workflow.toLayer hosted by workflowBundle Aug 26, 2026
@bweis
bweis force-pushed the spike/plain-workflow-syntax branch from 4d8157b to 0346977 Compare August 26, 2026 19:01
@bweis
bweis merged commit c7db0b6 into main Aug 26, 2026
5 checks passed
@bweis
bweis deleted the spike/plain-workflow-syntax branch August 26, 2026 19:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant